#include "stdafx.h"
#include <stdarg.h>
#include "console.h"

extern "C" __declspec(naked) void __cdecl _aullshr(void)
{
    __asm {
;
; Handle shifts of 64 bits or more (if shifting 64 bits or more, the result
; depends only on the high order bit of edx).
;
        cmp     cl,64
        jae     short RETZERO

;
; Handle shifts of between 0 and 31 bits
;
        cmp     cl, 32
        jae     short MORE32
        shrd    eax,edx,cl
        shr     edx,cl
        ret

;
; Handle shifts of between 32 and 63 bits
;
MORE32:
        mov     eax,edx
        xor     edx,edx
        and     cl,31
        shr     eax,cl
        ret

;
; return 0 in edx:eax
;
RETZERO:
        xor     eax,eax
        xor     edx,edx
        ret
    }
}


char* xstrcpy(char* pStrDst, char* pStrSrc)
{
	char* pRes = pStrDst;
	do
	{
		*pStrDst++ = *pStrSrc;
	}
	while (*pStrSrc++);

	return pRes;
}

static void kfail(char* pFmt, ...)
{
	va_list va;
	va_start(va, pFmt);

	puts("System failure: ");
	xprintf(pFmt, va);

	va_end(va);

	halt();
}

static QWORD GetTicksCount()
{
	QWORD val;
	QWORD* pVal = &val;
    __asm
	{
		rdtsc
        mov DWORD PTR [pVal + 0], eax;
		mov DWORD PTR [pVal + 4], edx
	};

	return val;
}

static int xstrlen(const char* pStr)
{
	int i = 0;
	while (*pStr++)
	{
		i++;
	}

	return i;
}

void xmemcpy(LPVOID pSrcArg, LPVOID pDestArg, DWORD size)
{
	LPBYTE pSrc = (LPBYTE)pSrcArg;
	LPBYTE pDest = (LPBYTE)pDestArg;

	if (pSrc == pDest || size < 1)
	{
		// we should do nothing :)
		return;
	}

	if (pSrc > pDest)
	{
		// move back - let's start from the beginning

		// let's move 4-byte blocks
		for (;size > 4; pSrc += 4, pDest += 4, size-= 4)
		{
			*(DWORD*)pDest = *(DWORD*)pSrc;
		}

		// let's move the rest
		for (;size; pSrc++, pDest++, size--)
		{
			*pDest = *pSrc;
		}
	}
	else
	{
		// move forward - let's start from the end
		pSrc += size;
		pDest += size;
	
		// let's move 4-byte blocks
		if (size > 4)
		{
			for (;size > 4; size-= 4)
			{
				pSrc -= 4;
				pDest -= 4;

				*(DWORD*)pDest = *(DWORD*)pSrc;
			}
		}

		// let's move the rest
		for (;size; size--)
		{
			pSrc--;
			pDest--;

			*pDest = *pSrc;
		}
	}
}

void xmemset_d(LPVOID pSrcArg, DWORD value, DWORD sizeInBytes)
{
	__asm
	{
		mov edi, pSrcArg;
		mov ecx, sizeInBytes;
		shr ecx, 2
		mov eax, value;

		rep stosd;
	};
}

void xmemset_w(LPVOID pSrcArg, WORD value, DWORD sizeInBytes)
{
	__asm
	{
		mov edi, pSrcArg;
		mov ecx, sizeInBytes;
		shr ecx, 1
		mov ax, value;

		rep stosw;
	};
}

void xmemset_b(LPVOID pSrcArg, BYTE value, DWORD sizeInBytes)
{
	__asm
	{
		mov edi, pSrcArg;
		mov ecx, sizeInBytes;
		mov al, value;

		rep stosb;
	};
}

